package org.dea.mapping;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;

import junit.framework.TestCase;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.sun.org.apache.xpath.internal.XPathAPI;

/**
 * Teste the <code>DocumentUtils</code> class.
 * 
 * @author Guilherme Mauro Germoglio - guiga@ourgrid.org
 * @author Flavio Roberto Santos - flavio@ourgrid.org
 */
public class DocumentUtilsTest extends TestCase {

	/*
	 * @see TestCase#setUp()
	 */
	protected void setUp() throws Exception {

		super.setUp();
	}


	public void testSimpleAreEqual() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );

		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testSimpleAreNotEqual() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple2.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

		assertFalse( DocumentUtils.areEqual( doc1, null ) );
		assertFalse( DocumentUtils.areEqual( null, doc2 ) );
	}


	public void testAreEqual() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );

		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

		Element nodeB = (Element) doc2.getElementsByTagName( "B" ).item( 0 );
		Element nodeD = (Element) doc2.getElementsByTagName( "D" ).item( 0 );
		nodeB.removeChild( nodeD );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );
	}


	public void testAreEqual2() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple1.xml", false );

		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

		Element nodeC = (Element) doc2.getElementsByTagName( "C" ).item( 0 );
		nodeC.removeAttribute( "ref" );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );
	}


	public void testEquals3() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple13.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple14.xml", false );

		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple3.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple4.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual1() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple4.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple5.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual2() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple6.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple7.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual3() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple8.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple9.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual4() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple10.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple11.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual5() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple12.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple13.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNotEqual6() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple15.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple16.xml", false );

		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testNodeList2List() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple8.xml", false );
		List list1 = DocumentUtils.nodeList2List( doc1.getDocumentElement().getChildNodes() );
		String[ ] nodesNames1 = { "b", "c" };
		for ( int k = 0; k < nodesNames1.length; k++ ) {
			Node node = (Node) list1.get( k );
			assertEquals( nodesNames1[k], node.getNodeName() );
		}
	}


	public void testNodeList2List1() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple17.xml", false );
		List list1 = DocumentUtils.nodeList2List( doc1.getDocumentElement().getChildNodes() );
		assertEquals( 0, list1.size() );
	}


	public void testEqualsWithTrim() throws Exception {

		DocumentUtils.trim( null );

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple18.xml", false );
		Document doc2 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "simple18-trim.xml", false );
		assertFalse( DocumentUtils.areEqual( doc1, doc2 ) );

		DocumentUtils.trim( doc1 );
		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

	}


	public void testPrintOutDocument() throws Exception {

		Document doc1 = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "full-example-1.cdl", true );
		String temp1 = "test" + File.separator + "temp1.cdl";
		DocumentUtils.printOutDocument( doc1, temp1 );
		Document doc2 = DocumentUtils.createDocument( temp1, true );

		assertTrue( DocumentUtils.areEqual( doc1, doc2 ) );

		File temp = new File( temp1 );
		temp.delete();
	}


	public void testGetNodes() throws Exception {

		Document doc = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator + "xml"
				+ File.separator + "nodeswithnamespace.xml", true );

		String[ ][ ] data = {
		// Syntax: { XPath to reach the root, namespace, prefix, localName,
								// number of nodes
								{ "/root", "http://one:1", "one", "HelloOne", "3" },
								{ "/root/one:HelloOne", "http://one:1", "one", "HelloOne", "0" },
								{ "/root/two", "http://four:4", "four", "WorldTwo", "1" },
								{ "/root/element", "http://three:3", "three", "WorldTwo", "0" },
								{ "/root/play", "http://one:1", "one", "helloone", "0" },
								{ "/root/play", "http://one:1", "one", "HelloOne", "2" },
								{ "/root", "http://two:2", "two", "WorldTwo", "1" },
								{ "/root", "http://three:3", "three", "HelloOne", "2" }, };

		for ( int i = 0; i < data.length; i++ ) {
			Node root = XPathAPI.selectSingleNode( doc.getDocumentElement(), data[i][0] );

			List nodes = DocumentUtils.getNodes( root, data[i][1], data[i][3] );
			assertEquals( Integer.parseInt( data[i][4] ), nodes.size() );

			for ( int j = 0; j < nodes.size(); j++ ) {
				Node aux = (Node) nodes.get( j );

				assertEquals( data[i][2] + ":" + data[i][3], aux.getNodeName() );
			}

		}
	}


	public void testGetValue() throws Exception {

		BufferedReader br = null;
		try {
			for ( int k = 1; k <= 10; k++ ) {
				Document doc = DocumentUtils.createDocument( "test" + File.separator + "parser" + File.separator
						+ "xml" + File.separator + k + "_nodevalue.xml", false );

				br = new BufferedReader( new FileReader( "test" + File.separator + "parser" + File.separator + "xml"
						+ File.separator + k + "_nodevalue_expected" ) );
				String answer = "";
				int c = -1;
				while ( (c = br.read()) != -1 ) {
					answer += (char) c;
				}

				assertEquals( answer, DocumentUtils.getValue( doc.getDocumentElement() ) );

			}
		} finally {
			if ( br != null ) {
				br.close();
			}
		}
	}

}
